package service

import (
	"admin-nexus-backend/internal/dto"
	"admin-nexus-backend/internal/model"
	"errors"
	"fmt"
	"io"
	"mime/multipart"
	"os"
	"path/filepath"
	"strings"
	"time"

	"gorm.io/gorm"
)

type AttachmentService struct {
	db *gorm.DB
}

func NewAttachmentService(db *gorm.DB) *AttachmentService {
	return &AttachmentService{db: db}
}

// GetList 获取附件列表
func (s *AttachmentService) GetList(params *dto.AttachmentQueryParams) ([]model.Attachment, int64, error) {
	var attachments []model.Attachment
	var total int64

	query := s.db.Model(&model.Attachment{})

	// 类别过滤
	if params.Category != "" {
		query = query.Where("category = ?", params.Category)
	}

	// 文件名模糊查询
	if params.Filename != "" {
		query = query.Where("filename LIKE ?", "%"+params.Filename+"%")
	}

	// 文件类型过滤
	if params.ImageType != "" {
		query = query.Where("image_type = ?", params.ImageType)
	}

	// 存储引擎过滤
	if params.Storage != "" {
		query = query.Where("storage = ?", params.Storage)
	}

	// Mime类型过滤
	if params.Mimetype != "" {
		query = query.Where("mimetype LIKE ?", "%"+params.Mimetype+"%")
	}

	// 文件大小范围过滤
	if params.MinFilesize != nil && *params.MinFilesize > 0 {
		query = query.Where("filesize >= ?", *params.MinFilesize)
	}
	if params.MaxFilesize != nil && *params.MaxFilesize > 0 {
		query = query.Where("filesize <= ?", *params.MaxFilesize)
	}

	// 时间范围过滤
	if params.StartTime != nil && *params.StartTime != "" {
		query = query.Where("upload_time >= ?", *params.StartTime)
	}
	if params.EndTime != nil && *params.EndTime != "" {
		query = query.Where("upload_time <= ?", *params.EndTime)
	}

	// 统计总数
	if err := query.Count(&total).Error; err != nil {
		return nil, 0, err
	}

	// 分页查询
	offset := (params.Page - 1) * params.PageSize
	if err := query.Order("id DESC").Offset(offset).Limit(params.PageSize).Find(&attachments).Error; err != nil {
		return nil, 0, err
	}

	return attachments, total, nil
}

// GetByID 根据ID获取附件
func (s *AttachmentService) GetByID(id uint) (*model.Attachment, error) {
	var attachment model.Attachment
	if err := s.db.First(&attachment, id).Error; err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, errors.New("附件不存在")
		}
		return nil, err
	}
	return &attachment, nil
}

// Create 创建附件
func (s *AttachmentService) Create(req *dto.AttachmentCreateRequest) (*model.Attachment, error) {
	// 如果未指定上传时间，使用当前时间
	uploadTime := req.UploadTime
	if uploadTime.IsZero() {
		uploadTime = time.Now()
	}

	// 如果未指定类别，使用默认值
	category := req.Category
	if category == "" {
		category = "unclassed"
	}

	// 如果未指定存储引擎，使用默认值
	storage := req.Storage
	if storage == "" {
		storage = "local"
	}

	attachment := &model.Attachment{
		Category:    category,
		URL:         req.URL,
		ImageWidth:  req.ImageWidth,
		ImageHeight: req.ImageHeight,
		ImageType:   req.ImageType,
		ImageFrames: req.ImageFrames,
		Filename:    req.Filename,
		Filesize:    req.Filesize,
		Mimetype:    req.Mimetype,
		Extparam:    req.Extparam,
		UploadTime:  uploadTime,
		Storage:     storage,
	}

	if err := s.db.Create(attachment).Error; err != nil {
		return nil, err
	}

	return attachment, nil
}

// Update 更新附件
func (s *AttachmentService) Update(id uint, req *dto.AttachmentUpdateRequest) (*model.Attachment, error) {
	attachment, err := s.GetByID(id)
	if err != nil {
		return nil, err
	}

	// 更新字段
	if req.Category != "" {
		attachment.Category = req.Category
	}
	if req.URL != "" {
		attachment.URL = req.URL
	}
	if req.ImageWidth >= 0 {
		attachment.ImageWidth = req.ImageWidth
	}
	if req.ImageHeight >= 0 {
		attachment.ImageHeight = req.ImageHeight
	}
	if req.ImageType != "" {
		attachment.ImageType = req.ImageType
	}
	if req.ImageFrames >= 0 {
		attachment.ImageFrames = req.ImageFrames
	}
	if req.Filename != "" {
		attachment.Filename = req.Filename
	}
	if req.Filesize >= 0 {
		attachment.Filesize = req.Filesize
	}
	if req.Mimetype != "" {
		attachment.Mimetype = req.Mimetype
	}
	if req.Extparam != "" {
		attachment.Extparam = req.Extparam
	}
	if req.UploadTime != nil {
		attachment.UploadTime = *req.UploadTime
	}
	if req.Storage != "" {
		attachment.Storage = req.Storage
	}

	if err := s.db.Save(attachment).Error; err != nil {
		return nil, err
	}

	return attachment, nil
}

// Delete 删除附件
func (s *AttachmentService) Delete(id uint) error {
	attachment, err := s.GetByID(id)
	if err != nil {
		return err
	}

	// 删除数据库记录
	if err := s.db.Delete(attachment).Error; err != nil {
		return err
	}

	// 如果是本地存储，尝试删除物理文件
	if attachment.Storage == "local" && attachment.URL != "" {
		// 构建完整路径（假设URL是相对路径）
		filePath := filepath.Join(".", attachment.URL)
		if _, err := os.Stat(filePath); err == nil {
			os.Remove(filePath) // 忽略删除错误
		}
	}

	return nil
}

// BatchDelete 批量删除附件
func (s *AttachmentService) BatchDelete(ids []uint) error {
	if len(ids) == 0 {
		return errors.New("请选择要删除的附件")
	}

	// 查询要删除的附件
	var attachments []model.Attachment
	if err := s.db.Where("id IN ?", ids).Find(&attachments).Error; err != nil {
		return err
	}

	// 删除数据库记录
	if err := s.db.Delete(&model.Attachment{}, ids).Error; err != nil {
		return err
	}

	// 删除物理文件
	for _, attachment := range attachments {
		if attachment.Storage == "local" && attachment.URL != "" {
			filePath := filepath.Join(".", attachment.URL)
			if _, err := os.Stat(filePath); err == nil {
				os.Remove(filePath) // 忽略删除错误
			}
		}
	}

	return nil
}

// Upload 上传文件
func (s *AttachmentService) Upload(file *multipart.FileHeader, category, extparam string) (*model.Attachment, error) {
	// 打开文件
	src, err := file.Open()
	if err != nil {
		return nil, err
	}
	defer src.Close()

	// 生成保存路径
	now := time.Now()
	dateDir := now.Format("20060102")
	uploadDir := filepath.Join("uploads", dateDir)

	// 确保目录存在
	if err := os.MkdirAll(uploadDir, 0755); err != nil {
		return nil, err
	}

	// 生成文件名（使用时间戳+原文件名）
	ext := filepath.Ext(file.Filename)
	filename := fmt.Sprintf("%d_%s", now.Unix(), file.Filename)
	savePath := filepath.Join(uploadDir, filename)

	// 创建目标文件
	dst, err := os.Create(savePath)
	if err != nil {
		return nil, err
	}
	defer dst.Close()

	// 复制文件内容
	if _, err := io.Copy(dst, src); err != nil {
		return nil, err
	}

	// 获取文件信息
	fileInfo, _ := dst.Stat()
	fileSize := fileInfo.Size()

	// 获取MIME类型
	mimeType := file.Header.Get("Content-Type")

	// 确定文件类型
	imageType := strings.TrimPrefix(ext, ".")

	// 如果未指定类别，使用默认值
	if category == "" {
		category = "unclassed"
	}

	// 创建附件记录
	attachment := &model.Attachment{
		Category:    category,
		URL:         "/" + strings.ReplaceAll(savePath, "\\", "/"),
		ImageWidth:  0,
		ImageHeight: 0,
		ImageType:   imageType,
		ImageFrames: 0,
		Filename:    file.Filename,
		Filesize:    fileSize,
		Mimetype:    mimeType,
		Extparam:    extparam,
		UploadTime:  now,
		Storage:     "local",
	}

	if err := s.db.Create(attachment).Error; err != nil {
		// 如果创建记录失败，删除已上传的文件
		os.Remove(savePath)
		return nil, err
	}

	return attachment, nil
}

// GetCategories 获取所有类别
func (s *AttachmentService) GetCategories() ([]string, error) {
	var categories []string
	if err := s.db.Model(&model.Attachment{}).
		Distinct("category").
		Pluck("category", &categories).Error; err != nil {
		return nil, err
	}
	return categories, nil
}

// GetStorageEngines 获取所有存储引擎
func (s *AttachmentService) GetStorageEngines() ([]string, error) {
	var engines []string
	if err := s.db.Model(&model.Attachment{}).
		Distinct("storage").
		Pluck("storage", &engines).Error; err != nil {
		return nil, err
	}
	return engines, nil
}
